#import "RhoHTTPConnection.h"
#import "GCDAsyncSocket.h"
#import "HTTPServer.h"
#import "HTTPMessage.h"
#import "HTTPResponse.h"
#import "HTTPAuthenticationRequest.h"
#import "DDNumber.h"
#import "DDRange.h"
#import "DDData.h"
#import "HTTPFileResponse.h"
#import "HTTPAsyncFileResponse.h"
#import "WebSocket.h"
#import "HTTPLogging.h"


extern const char* rho_http_direct_request( const char* method, const char* uri, const char* query, const void* headers, const char* body, int bodylen, int* responseLength );
extern void rho_http_free_response( const char* data );

extern void* rho_http_init_headers_list();
extern void rho_http_add_header( void* list, const char* name, const char* value );
extern void rho_http_free_headers_list( void* list );

extern int rho_conf_getBool(const char* szName);

#define HTTP_RESPONSE                      90
#define HTTP_FINAL_RESPONSE                91
#define TIMEOUT_WRITE_BODY                   -1

static const int ddLogLevel = LOG_LEVEL_VERBOSE;


// array size is 2493
static const int TestCertificateSize = 2493;
static const unsigned char TestCertificateBytes[]  = {
  0x30, 0x82, 0x09, 0xb9, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48,
  0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x09, 0x71, 0x04, 0x82, 0x09, 0x6d, 0x30, 0x82,
  0x09, 0x69, 0x30, 0x82, 0x03, 0xef, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
  0x06, 0xa0, 0x82, 0x03, 0xe0, 0x30, 0x82, 0x03, 0xdc, 0x02, 0x01, 0x00, 0x30, 0x82, 0x03, 0xd5,
  0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x30, 0x1c, 0x06, 0x0a, 0x2a,
  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06, 0x30, 0x0e, 0x04, 0x08, 0xd5, 0x86, 0xb6,
  0xd2, 0x83, 0x73, 0xd2, 0x73, 0x02, 0x02, 0x08, 0x00, 0x80, 0x82, 0x03, 0xa8, 0x71, 0xc4, 0xff,
  0x9a, 0x40, 0xad, 0x7c, 0xa3, 0x73, 0x38, 0xd1, 0xe2, 0x0a, 0x04, 0x61, 0x3b, 0x6d, 0x2f, 0xe7,
  0x45, 0x43, 0x59, 0x75, 0x79, 0x12, 0x03, 0xb4, 0xa3, 0x83, 0xb7, 0x07, 0xdb, 0xd2, 0xa7, 0x39,
  0xe1, 0x2e, 0x4e, 0x71, 0xa0, 0x79, 0xc9, 0x7d, 0x40, 0xa2, 0x55, 0xd5, 0xed, 0xb8, 0x08, 0xcd,
  0xdc, 0xa5, 0xdc, 0x90, 0x2d, 0xd8, 0x17, 0xe6, 0x63, 0x60, 0x62, 0x21, 0xf3, 0xed, 0x85, 0xb0,
  0x1c, 0x1f, 0x7f, 0x7b, 0xe1, 0xd5, 0x9c, 0x5f, 0xaf, 0x93, 0x2a, 0x89, 0xb7, 0xe7, 0x02, 0x53,
  0x89, 0x2a, 0xb7, 0xc7, 0x6d, 0x4a, 0x02, 0xa4, 0xf7, 0x81, 0x18, 0xb7, 0x20, 0x62, 0x9e, 0x62,
  0x6e, 0xd9, 0xec, 0x7d, 0x7a, 0xca, 0x61, 0x41, 0xfc, 0x92, 0xeb, 0xba, 0x83, 0x0a, 0xbd, 0xb9,
  0x90, 0xd6, 0xca, 0xed, 0x2f, 0xc6, 0x9f, 0x43, 0xf9, 0xad, 0xe5, 0xd5, 0xe0, 0x5b, 0x08, 0xb7,
  0xfc, 0x39, 0x7f, 0x1c, 0x64, 0x72, 0x9a, 0x95, 0xdc, 0x8f, 0x9c, 0xd2, 0x40, 0xdd, 0x18, 0x91,
  0xea, 0x1f, 0x96, 0x81, 0x83, 0x70, 0x46, 0x82, 0x21, 0xc5, 0x0d, 0x2d, 0x75, 0xd6, 0x3a, 0xa8,
  0xd7, 0x80, 0xd1, 0xdb, 0x7a, 0x88, 0xda, 0x3a, 0xd1, 0x16, 0xd4, 0x4a, 0x3d, 0xfa, 0x48, 0x55,
  0xfa, 0xd9, 0x33, 0x6e, 0xa3, 0x69, 0xdc, 0xa3, 0x78, 0x4f, 0x90, 0xf4, 0xa4, 0x7e, 0xdd, 0xd9,
  0xa1, 0xbe, 0xf6, 0xc5, 0x1f, 0x43, 0xc7, 0x36, 0x46, 0xe0, 0xaf, 0xeb, 0x3d, 0x7f, 0xcc, 0xb6,
  0xaf, 0xb7, 0xd7, 0x34, 0x8f, 0xa2, 0xdf, 0x68, 0xfd, 0xc5, 0x7d, 0x7e, 0x0e, 0xaa, 0x96, 0x29,
  0x8f, 0xbd, 0x61, 0x3b, 0xcc, 0xba, 0xad, 0xef, 0x30, 0xa9, 0x95, 0xaa, 0x49, 0x56, 0xd5, 0x86,
  0x52, 0x73, 0x75, 0x62, 0x80, 0xfd, 0xa5, 0xb5, 0xf4, 0x2c, 0x69, 0xc4, 0x3a, 0x64, 0x7b, 0x07,
  0xa0, 0xab, 0xac, 0xdb, 0xbb, 0x4b, 0xf7, 0xcb, 0xcd, 0xa0, 0xd6, 0xe9, 0xd1, 0x87, 0x6f, 0x77,
  0x01, 0x19, 0x67, 0x09, 0x17, 0xaf, 0x7e, 0x8d, 0x58, 0x2d, 0x0e, 0x53, 0xbc, 0x8e, 0xd0, 0x24,
  0x92, 0xcc, 0x3e, 0xbb, 0x74, 0xd1, 0xb3, 0x3f, 0xc6, 0x6a, 0x3b, 0x1d, 0xce, 0x85, 0x44, 0xe6,
  0xbe, 0x31, 0x07, 0x4b, 0xdc, 0x55, 0xbb, 0xb7, 0xe5, 0xcd, 0x22, 0x04, 0xae, 0xba, 0x45, 0x99,
  0xcf, 0xf4, 0xbc, 0x73, 0x51, 0x5f, 0x71, 0xc4, 0x3d, 0xa8, 0x79, 0x52, 0xae, 0xb6, 0x03, 0x89,
  0x7f, 0x1c, 0x3c, 0xd8, 0x6c, 0x6b, 0x91, 0x65, 0xab, 0x19, 0x43, 0xa6, 0x96, 0x2a, 0x7d, 0x8e,
  0x70, 0x19, 0x7c, 0x25, 0xc8, 0x92, 0xd9, 0x08, 0xa1, 0x6f, 0x21, 0xf8, 0x05, 0x50, 0xe1, 0xd4,
  0xa6, 0xf4, 0xe1, 0x82, 0xf1, 0x7b, 0xa8, 0x6e, 0x95, 0x46, 0x54, 0xc4, 0xb2, 0x8e, 0x87, 0xa7,
  0xff, 0x5c, 0x9e, 0x95, 0x76, 0xdc, 0xa5, 0x6d, 0x8e, 0xce, 0xd1, 0x9a, 0x4f, 0x15, 0x16, 0x61,
  0x1c, 0x41, 0xba, 0x42, 0xb6, 0xac, 0x1e, 0xdb, 0xb0, 0xf4, 0x90, 0xff, 0x10, 0x9f, 0xa1, 0xb9,
  0xb5, 0xe2, 0x65, 0x95, 0xe8, 0xd2, 0x14, 0x59, 0xda, 0x15, 0x68, 0xf7, 0x45, 0xdc, 0x1c, 0xa8,
  0xd3, 0x85, 0xbc, 0xd5, 0x72, 0x9f, 0x2b, 0xb3, 0xdd, 0x5c, 0xa8, 0xde, 0x1e, 0xb6, 0x96, 0xef,
  0x8a, 0xd5, 0xe0, 0x46, 0xa3, 0xb9, 0xf5, 0x05, 0xfb, 0x5b, 0x39, 0x06, 0x12, 0x33, 0xc6, 0x96,
  0xb5, 0x8a, 0xa3, 0x16, 0xe4, 0x50, 0xff, 0xa3, 0xf7, 0xb9, 0x7d, 0xaa, 0xbe, 0x0e, 0x29, 0x0b,
  0x76, 0x9b, 0xc1, 0xaa, 0x85, 0xf5, 0x46, 0x90, 0xde, 0xd2, 0x0e, 0x8a, 0xb7, 0x63, 0xf0, 0xce,
  0xd4, 0x1b, 0x8d, 0x55, 0x64, 0xf6, 0x22, 0x65, 0x9c, 0x2c, 0x11, 0xae, 0xd8, 0x54, 0x81, 0x22,
  0xab, 0xef, 0xf0, 0x5c, 0x84, 0xb5, 0x4d, 0x04, 0xcc, 0x21, 0xc8, 0x88, 0x68, 0xe4, 0xfd, 0x3d,
  0x8f, 0x55, 0xf0, 0xba, 0x6c, 0x03, 0x48, 0x1f, 0x72, 0x2a, 0x40, 0xcf, 0x5d, 0xe9, 0xdb, 0xea,
  0x4e, 0xb1, 0xef, 0x9b, 0x29, 0x0d, 0x89, 0x8b, 0xbd, 0x3c, 0x98, 0x70, 0x42, 0xe1, 0x0c, 0xa0,
  0x6c, 0x12, 0xdb, 0xb8, 0xb0, 0x1f, 0x4b, 0x19, 0xb8, 0xa9, 0x0f, 0x52, 0x6c, 0x4a, 0xf7, 0xf6,
  0x60, 0x70, 0xef, 0xc9, 0xe8, 0xfb, 0xee, 0x71, 0x7b, 0x80, 0xf9, 0x38, 0x1b, 0xc8, 0x28, 0x93,
  0xf0, 0x08, 0xbd, 0xc9, 0x78, 0x2a, 0x9f, 0x3c, 0x9c, 0x84, 0xc4, 0x07, 0xd9, 0xda, 0x0c, 0xbf,
  0x40, 0x78, 0x94, 0x4e, 0x82, 0xdd, 0x7a, 0x76, 0x8f, 0xe5, 0xb9, 0xce, 0xc8, 0x8b, 0x46, 0x05,
  0xfb, 0x30, 0x94, 0xa6, 0xa4, 0xe6, 0x04, 0x25, 0x65, 0x61, 0xf5, 0xc5, 0x3d, 0x3a, 0x88, 0xfa,
  0x46, 0xe6, 0xae, 0xab, 0xf2, 0x7d, 0xdc, 0x3a, 0x5d, 0xf3, 0xcc, 0xe8, 0xdf, 0x32, 0x72, 0x15,
  0x69, 0x80, 0x90, 0xa5, 0x53, 0x94, 0xfc, 0x99, 0x9d, 0x09, 0x2c, 0xe6, 0x9b, 0xca, 0xf9, 0x0c,
  0xce, 0x6c, 0x9b, 0x52, 0xe2, 0xcb, 0xf6, 0xe1, 0x04, 0xd5, 0x66, 0x48, 0x0a, 0x61, 0x39, 0xb0,
  0xc7, 0x4f, 0x92, 0x30, 0x74, 0xc9, 0x1d, 0x43, 0x5e, 0x22, 0xe5, 0xdd, 0x6d, 0x98, 0x79, 0xc0,
  0xa9, 0x77, 0xf5, 0xae, 0xa6, 0x47, 0xc4, 0x3c, 0x31, 0x7d, 0x0b, 0x0a, 0x55, 0x1b, 0xf3, 0x97,
  0xd2, 0x47, 0x61, 0xda, 0x03, 0x6f, 0x31, 0xda, 0xcb, 0x76, 0xc6, 0xc3, 0x1a, 0x3a, 0x39, 0xc6,
  0xaf, 0x9f, 0x45, 0x2d, 0x37, 0xad, 0xd7, 0xdd, 0xc0, 0x28, 0x92, 0x5d, 0x9e, 0x94, 0x31, 0x30,
  0x5b, 0xc9, 0xb6, 0xd8, 0x77, 0x7f, 0x7a, 0x7b, 0x07, 0xf3, 0xa1, 0xd6, 0x13, 0x63, 0x8d, 0xae,
  0xdc, 0x67, 0x7c, 0x96, 0xf8, 0x71, 0x69, 0x78, 0xfe, 0x41, 0x72, 0x49, 0x2a, 0x9c, 0x3c, 0x16,
  0x8b, 0x6b, 0x28, 0xaa, 0xb9, 0x18, 0xbf, 0xb7, 0x6d, 0x02, 0xef, 0xce, 0x0e, 0xd7, 0x1d, 0x1f,
  0x18, 0xdb, 0x9d, 0x9a, 0xcc, 0x0d, 0x1d, 0x97, 0x1b, 0x69, 0x1b, 0x32, 0x74, 0x8c, 0xf1, 0xd6,
  0xbc, 0xc1, 0x9c, 0xb4, 0x8a, 0x96, 0x01, 0xa6, 0xb8, 0xb9, 0xda, 0x43, 0xdb, 0xa7, 0x9a, 0x70,
  0xb4, 0x5d, 0xd7, 0x9f, 0xab, 0xb9, 0x37, 0x8e, 0x85, 0x91, 0x1e, 0xb4, 0xb4, 0xff, 0x8d, 0xe3,
  0x5e, 0xf2, 0x8c, 0x5b, 0x5b, 0x5e, 0x8a, 0x08, 0xde, 0x42, 0xa2, 0xaa, 0x92, 0xcc, 0x84, 0x82,
  0x1f, 0x6e, 0x56, 0xf9, 0x7c, 0x38, 0x3b, 0x7c, 0x12, 0xe7, 0x26, 0x0b, 0xf0, 0xd3, 0x85, 0xc1,
  0xb2, 0xad, 0xf8, 0x6a, 0x43, 0xf8, 0xb9, 0x70, 0xb0, 0xb7, 0x09, 0x0a, 0xc4, 0xa9, 0x41, 0xce,
  0x2e, 0x04, 0x3b, 0xd0, 0xa8, 0xeb, 0x6c, 0x44, 0x54, 0xd1, 0x8b, 0xbe, 0x52, 0xac, 0x8b, 0x44,
  0xcf, 0x36, 0x91, 0x75, 0xc3, 0xfe, 0xe3, 0x00, 0x09, 0x24, 0x78, 0x7e, 0xa5, 0x0f, 0x73, 0x50,
  0x73, 0xbd, 0x16, 0xb2, 0xdb, 0x30, 0x82, 0x05, 0x72, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
  0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x05, 0x63, 0x04, 0x82, 0x05, 0x5f, 0x30, 0x82, 0x05, 0x5b,
  0x30, 0x82, 0x05, 0x57, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01,
  0x02, 0xa0, 0x82, 0x04, 0xee, 0x30, 0x82, 0x04, 0xea, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48,
  0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0x87, 0x8d, 0x93, 0x30, 0x2f,
  0x36, 0x4e, 0x7a, 0x02, 0x02, 0x08, 0x00, 0x04, 0x82, 0x04, 0xc8, 0x94, 0x49, 0xe9, 0x45, 0xc1,
  0xb4, 0xb0, 0x8f, 0x37, 0x43, 0x35, 0x67, 0xd3, 0x9a, 0x2f, 0x54, 0x25, 0xf3, 0x00, 0x80, 0x06,
  0x8a, 0x09, 0x3b, 0x54, 0x88, 0xbf, 0x31, 0xcb, 0xe6, 0x0f, 0x95, 0xdf, 0x54, 0xb2, 0x32, 0x3d,
  0x5e, 0x88, 0x1a, 0x73, 0xf2, 0xd4, 0x5e, 0xc3, 0x3e, 0xa0, 0xfd, 0xe1, 0xd9, 0x3d, 0x38, 0x1c,
  0x30, 0x86, 0x7d, 0x9d, 0x9f, 0x2a, 0x1c, 0xfc, 0x54, 0xf9, 0x2e, 0x55, 0x7d, 0x2a, 0x5e, 0x64,
  0xd7, 0x8a, 0xb8, 0xb7, 0x32, 0x95, 0xb9, 0x58, 0x09, 0x00, 0x2e, 0xe7, 0xd4, 0x9c, 0x97, 0xa0,
  0x0f, 0x6e, 0x35, 0x90, 0xf1, 0x19, 0x4a, 0xa4, 0xc3, 0x72, 0x9f, 0xf7, 0x7e, 0x1f, 0x29, 0x72,
  0x19, 0xb2, 0x9c, 0xd5, 0x8d, 0x52, 0xff, 0xde, 0x38, 0x44, 0x62, 0x1d, 0xf0, 0x8b, 0x15, 0xb6,
  0x52, 0x03, 0xe6, 0xcc, 0x8b, 0x7b, 0x0b, 0x13, 0x96, 0xde, 0x47, 0x3e, 0x42, 0x64, 0xbb, 0xe1,
  0x44, 0x64, 0xe2, 0x15, 0x8e, 0x9f, 0x55, 0xaa, 0x19, 0x94, 0x14, 0x8e, 0x5d, 0xb5, 0x9e, 0x52,
  0xe6, 0x22, 0xa1, 0xd5, 0xeb, 0xc4, 0xa6, 0x54, 0xff, 0xd0, 0x80, 0x0e, 0xec, 0xb3, 0x08, 0x02,
  0xcb, 0xcc, 0xea, 0xc8, 0x03, 0xad, 0xc2, 0x6e, 0x98, 0x27, 0x1e, 0xc6, 0xc3, 0x36, 0x96, 0x4a,
  0x22, 0xfb, 0xf9, 0x81, 0xbf, 0x25, 0x3a, 0x50, 0xfc, 0xe6, 0xda, 0x59, 0x83, 0xf1, 0x62, 0xa3,
  0x08, 0xe0, 0xf2, 0x43, 0x13, 0x30, 0x2a, 0x2e, 0x07, 0xaa, 0xc4, 0xf8, 0xf0, 0x17, 0x63, 0x56,
  0x98, 0xc3, 0x69, 0x81, 0x67, 0x18, 0x93, 0x8a, 0x42, 0x32, 0x27, 0x21, 0x28, 0x9d, 0xcc, 0x97,
  0x89, 0x70, 0x7c, 0xd1, 0x92, 0xd5, 0x35, 0xe1, 0x9b, 0x04, 0x95, 0xda, 0x18, 0xfd, 0x0b, 0xa4,
  0xb6, 0xc8, 0x4d, 0x22, 0x39, 0x46, 0xe9, 0xee, 0xd4, 0x70, 0x9a, 0x00, 0x9b, 0xae, 0xbc, 0xfe,
  0x97, 0xc7, 0xb0, 0x5e, 0x62, 0x1b, 0x5d, 0x77, 0x4e, 0xfc, 0xd1, 0x93, 0xf1, 0x36, 0xc7, 0x4b,
  0xbf, 0xa0, 0x4b, 0x1e, 0x2d, 0xa8, 0x3e, 0x76, 0xab, 0xc3, 0xa2, 0xec, 0x81, 0xd3, 0x63, 0x6c,
  0xdf, 0x0f, 0xcd, 0x5a, 0x3c, 0xe9, 0x55, 0x11, 0x92, 0x82, 0x75, 0x93, 0x66, 0xb9, 0xcd, 0x6a,
  0xdf, 0xd7, 0x92, 0xd7, 0xf0, 0xd8, 0xd3, 0x50, 0x7d, 0xb6, 0x97, 0x0c, 0x82, 0xf9, 0x0b, 0xd5,
  0xf6, 0x8e, 0x4d, 0x4c, 0xdb, 0xd5, 0xf7, 0x4d, 0x06, 0xa2, 0x94, 0xca, 0x0d, 0x96, 0x66, 0x73,
  0x0d, 0x2c, 0x2a, 0xff, 0xbc, 0xe2, 0x63, 0x09, 0xe5, 0xb5, 0xc1, 0x43, 0xb3, 0xbd, 0x07, 0x2d,
  0xbb, 0x15, 0x65, 0xeb, 0x6c, 0x05, 0x4d, 0xa4, 0xf8, 0x1d, 0xcb, 0xb5, 0x62, 0xaf, 0x12, 0xf9,
  0xee, 0x17, 0x7f, 0xdf, 0xea, 0xd3, 0x01, 0xd1, 0x6c, 0x28, 0x16, 0x84, 0x5d, 0xdd, 0x4e, 0xac,
  0xae, 0xf3, 0xf8, 0x9a, 0x15, 0x3e, 0xb9, 0xc4, 0xcc, 0x83, 0x18, 0x7e, 0x47, 0x9a, 0x6b, 0x7e,
  0x9f, 0xc6, 0x54, 0xbc, 0xba, 0xc1, 0xe4, 0xd9, 0x85, 0x57, 0xeb, 0x07, 0xa5, 0x0c, 0x1a, 0x8c,
  0x4d, 0xa4, 0xeb, 0x5f, 0xff, 0xde, 0xac, 0x57, 0x16, 0xcf, 0xeb, 0xdf, 0xda, 0x93, 0x10, 0x18,
  0xaa, 0x5d, 0x9b, 0x9c, 0x51, 0x40, 0x8e, 0xfa, 0xcd, 0x38, 0x63, 0x6a, 0xf1, 0xcc, 0xed, 0x25,
  0xc3, 0x65, 0x27, 0xad, 0x54, 0x61, 0x7c, 0x81, 0xf4, 0x81, 0xf5, 0xcf, 0x16, 0xf0, 0x64, 0x45,
  0xf5, 0x55, 0x18, 0x47, 0x25, 0x31, 0xbe, 0x9a, 0x9b, 0xa8, 0xce, 0xde, 0x68, 0x1d, 0xcd, 0x35,
  0x64, 0x9b, 0x03, 0xcb, 0x81, 0x89, 0x63, 0xa4, 0xb4, 0xcc, 0x21, 0xfa, 0xd2, 0x2a, 0x73, 0x3d,
  0x46, 0x82, 0x0c, 0xed, 0x1c, 0x29, 0xc5, 0xf7, 0xcc, 0x9a, 0x8b, 0x38, 0xe2, 0xf7, 0x1c, 0xa9,
  0xaa, 0x2e, 0xf2, 0xc9, 0x40, 0x91, 0x39, 0x80, 0xf1, 0x8c, 0x7d, 0x2e, 0x38, 0x64, 0x1b, 0xc5,
  0x8e, 0xfc, 0xb7, 0x97, 0x58, 0xc9, 0xe1, 0x0b, 0x98, 0x54, 0x1f, 0x53, 0x24, 0xf0, 0x92, 0xeb,
  0xdf, 0x91, 0x69, 0x8f, 0x3b, 0x5c, 0xa5, 0x76, 0xb4, 0x48, 0x98, 0x8e, 0x56, 0xd8, 0xab, 0x8d,
  0x5a, 0x59, 0xcb, 0x9a, 0x4a, 0x85, 0x74, 0x9d, 0xbd, 0x18, 0x42, 0x5d, 0xa1, 0xbb, 0x64, 0x14,
  0xda, 0xd1, 0x95, 0x4e, 0xb3, 0x98, 0x2b, 0x98, 0xa1, 0x82, 0xc2, 0x11, 0x27, 0x62, 0x55, 0xde,
  0xd2, 0x7f, 0x67, 0x6a, 0xab, 0x40, 0x82, 0x6e, 0xa8, 0x8e, 0x53, 0x21, 0x94, 0xea, 0xda, 0x10,
  0x60, 0xd7, 0xe3, 0xaf, 0x89, 0x06, 0xf0, 0x0e, 0xc3, 0x77, 0x6f, 0x04, 0x35, 0xdc, 0x38, 0xc9,
  0xa9, 0xae, 0x10, 0x71, 0xe9, 0x70, 0xd1, 0xf2, 0xe0, 0x73, 0x7f, 0x27, 0xb5, 0xb3, 0xf3, 0x7f,
  0x05, 0x94, 0x7b, 0xd6, 0x44, 0x6f, 0x8d, 0xd7, 0x1e, 0x0a, 0x0e, 0x67, 0xb0, 0xe2, 0x4d, 0x5a,
  0x82, 0xae, 0x0c, 0x41, 0x6d, 0x32, 0x69, 0x67, 0xa4, 0x2b, 0x40, 0x69, 0x22, 0x87, 0xe5, 0xf2,
  0x3e, 0xf8, 0x26, 0x5e, 0x16, 0x31, 0xdf, 0x1a, 0x27, 0x32, 0x52, 0x76, 0x56, 0x5f, 0xbb, 0xae,
  0xe6, 0xe6, 0xff, 0xf5, 0x19, 0x34, 0x01, 0x14, 0x7f, 0x8d, 0xba, 0xa1, 0xbe, 0x1c, 0x18, 0x5a,
  0xd4, 0x70, 0x2e, 0x6b, 0x54, 0x44, 0x2c, 0x40, 0x0b, 0x1b, 0xee, 0x8b, 0xb7, 0x5b, 0xaa, 0xb9,
  0x0b, 0xff, 0x49, 0xda, 0x82, 0x23, 0x57, 0x87, 0x91, 0x5a, 0xdf, 0xad, 0x7c, 0xae, 0xb3, 0x02,
  0xe9, 0x01, 0xf0, 0x67, 0x6c, 0x72, 0xc4, 0x86, 0x47, 0x70, 0xd4, 0x58, 0xe5, 0x44, 0x82, 0xdb,
  0x9c, 0x38, 0x41, 0x72, 0x30, 0x69, 0xf6, 0xfc, 0x9f, 0x2b, 0xde, 0x49, 0x0a, 0x74, 0x1b, 0xb3,
  0x89, 0x9b, 0x51, 0x45, 0x26, 0xde, 0xf3, 0x11, 0x24, 0x2e, 0x37, 0x73, 0xfb, 0xe2, 0x3b, 0x62,
  0x8e, 0x76, 0x29, 0xb1, 0xbb, 0x67, 0xd5, 0x56, 0x37, 0x4b, 0x4c, 0x7e, 0x78, 0xb6, 0xe0, 0xd6,
  0x82, 0x63, 0x39, 0x0c, 0x60, 0xc8, 0xf8, 0x7e, 0x7e, 0xd5, 0xb3, 0xa5, 0x74, 0x19, 0x22, 0x10,
  0x29, 0x86, 0x4e, 0x20, 0xa1, 0x10, 0xed, 0x6e, 0x20, 0xdf, 0xd5, 0xfe, 0xac, 0x89, 0xa9, 0xba,
  0x67, 0x37, 0xe5, 0xab, 0xdc, 0x59, 0x8c, 0xdc, 0x35, 0x59, 0x66, 0x36, 0x29, 0x8a, 0xfb, 0xa2,
  0xbe, 0xc8, 0x6a, 0xdf, 0x1c, 0xf9, 0x33, 0xd9, 0x65, 0x66, 0x85, 0x31, 0x45, 0xcf, 0x13, 0x15,
  0xa5, 0x9d, 0x0a, 0x03, 0xa0, 0x65, 0x53, 0x65, 0xe7, 0x94, 0x6d, 0x26, 0x5a, 0xca, 0x76, 0xd4,
  0x7a, 0x8f, 0xb9, 0x28, 0xfc, 0xd5, 0xfb, 0xe3, 0x8f, 0xc8, 0x9a, 0x6e, 0x38, 0x0e, 0x8d, 0x79,
  0x74, 0xf3, 0xdd, 0x81, 0x51, 0xb7, 0x1f, 0x8c, 0x9d, 0x30, 0xe0, 0x7b, 0x14, 0xc2, 0x74, 0x9f,
  0x3a, 0x33, 0x1d, 0x46, 0x3e, 0x1f, 0xbe, 0x90, 0x15, 0x72, 0x92, 0x92, 0x5d, 0xd9, 0xab, 0xbf,
  0xc9, 0x7f, 0xad, 0xe0, 0xc9, 0xa0, 0xca, 0xa9, 0x96, 0x8a, 0x22, 0xca, 0x60, 0x42, 0x86, 0xb9,
  0xe3, 0x0a, 0xd1, 0x04, 0x4d, 0xfc, 0xa3, 0x07, 0x03, 0xb3, 0x26, 0x28, 0xee, 0x5d, 0x94, 0x65,
  0x23, 0x73, 0x44, 0xdb, 0x36, 0xd8, 0xed, 0x91, 0x93, 0x5e, 0xcb, 0xfb, 0x93, 0x7e, 0x21, 0xcc,
  0x24, 0x6a, 0xe5, 0xee, 0x7d, 0xd4, 0xdc, 0x43, 0xba, 0xa0, 0x23, 0xbd, 0xed, 0x16, 0x31, 0x28,
  0x2d, 0x99, 0xfe, 0x62, 0x4a, 0x26, 0xe1, 0x2b, 0xc4, 0x36, 0xb1, 0x2f, 0x80, 0x94, 0xd6, 0x90,
  0x97, 0x53, 0x91, 0xf8, 0x8b, 0xf3, 0xd3, 0x8c, 0x86, 0x79, 0xd3, 0x5a, 0xae, 0x7b, 0x20, 0x8d,
  0x8e, 0xba, 0x2d, 0x07, 0xd9, 0xb9, 0xdf, 0x05, 0x2d, 0x50, 0x25, 0x32, 0xd7, 0xde, 0xc5, 0x79,
  0xb3, 0x36, 0xa1, 0xd3, 0x65, 0xac, 0x8f, 0x24, 0x24, 0xbe, 0x64, 0x1a, 0xa8, 0x52, 0x9b, 0x34,
  0x65, 0x31, 0x80, 0xe8, 0x41, 0xbf, 0x75, 0xd5, 0xa2, 0x45, 0x5d, 0xeb, 0x36, 0x75, 0xc6, 0x06,
  0x18, 0x37, 0xa5, 0x0b, 0x58, 0x41, 0xcb, 0x36, 0x4c, 0xef, 0x2b, 0x22, 0x20, 0xa4, 0x3f, 0x37,
  0xe8, 0xd8, 0xf9, 0x72, 0xe5, 0x8e, 0xb5, 0x86, 0x51, 0xed, 0x87, 0xb7, 0x95, 0x05, 0x5b, 0xc5,
  0xa2, 0x8a, 0x5d, 0x19, 0xc5, 0xe0, 0xdd, 0x25, 0x54, 0x28, 0x3d, 0x33, 0x0a, 0xf6, 0x30, 0xce,
  0x4e, 0xae, 0x2d, 0x57, 0x02, 0x75, 0x50, 0xb5, 0xf4, 0x07, 0xb2, 0xcf, 0xf1, 0xd0, 0x00, 0x04,
  0x87, 0x03, 0x43, 0x02, 0x96, 0xca, 0x3e, 0x6d, 0xb7, 0x54, 0xe6, 0xa1, 0xda, 0xf9, 0xf8, 0xca,
  0x84, 0xeb, 0x41, 0x26, 0x59, 0x32, 0x40, 0x5a, 0xa4, 0x7b, 0x78, 0xc3, 0x82, 0x17, 0xf4, 0x0d,
  0xbf, 0xe7, 0xa6, 0xd8, 0x3c, 0x85, 0xa7, 0x0d, 0x42, 0x40, 0x72, 0x66, 0x33, 0x04, 0x63, 0x1b,
  0x2e, 0xe0, 0xf3, 0x40, 0x0e, 0x5f, 0x87, 0x9b, 0xd5, 0x4f, 0x33, 0xe8, 0x2f, 0x5f, 0x60, 0x56,
  0x41, 0x8e, 0x56, 0xf4, 0xe4, 0xb2, 0x9d, 0xcc, 0xc2, 0x88, 0xa3, 0x94, 0xed, 0x93, 0x4a, 0x32,
  0x60, 0xd4, 0xdf, 0x31, 0x56, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
  0x09, 0x14, 0x31, 0x22, 0x1e, 0x20, 0x00, 0x4d, 0x00, 0x4f, 0x00, 0x48, 0x00, 0x55, 0x00, 0x53,
  0x00, 0x5f, 0x00, 0x53, 0x00, 0x53, 0x00, 0x4c, 0x00, 0x5f, 0x00, 0x53, 0x00, 0x45, 0x00, 0x52,
  0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x30, 0x23, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
  0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14, 0xa7, 0xd8, 0x82, 0x2e, 0xd6, 0x6a, 0x57, 0x5f, 0x47,
  0xfc, 0xa0, 0x40, 0x4b, 0x26, 0xe6, 0xd2, 0x86, 0x4b, 0x06, 0x3a, 0x30, 0x30, 0x30, 0x21, 0x30,
  0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0x5e, 0xe6, 0x69, 0x33,
  0xe8, 0xd3, 0xd1, 0x26, 0xc0, 0x23, 0x27, 0xf9, 0x5a, 0xe6, 0x5c, 0xb1, 0xaf, 0x24, 0x9f, 0x74,
  0x04, 0x08, 0x82, 0x61, 0xc4, 0x10, 0x0c, 0x82, 0x12, 0x94, 0x02, 0x01, 0x01
};

@implementation RhoHTTPConnection


- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path
{

    if ([method isEqualToString:@"GET"])
        return YES;
    
    if ([method isEqualToString:@"POST"])
        return YES;
    
    if ([method isEqualToString:@"PUT"])
        return YES;

    if ([method isEqualToString:@"HEAD"])
        return YES;
        
    return NO;
}


- (BOOL)isSecureServer
{
  //HTTPLogTrace();
    if (  rho_conf_getBool("ios_https_local_server") ) {
        return YES;
    }
  return NO;
}



- (NSArray *)sslIdentityAndCertificates
{
    
    SecIdentityRef identityRef = NULL;
    SecCertificateRef certificateRef = NULL;
    SecTrustRef trustRef = NULL;
    
    //NSString *thePath = [[NSBundle mainBundle] pathForResource:@"TestCertificate" ofType:@"p12"];
    //NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
    NSData *PKCS12Data = [[NSData alloc] initWithBytes:TestCertificateBytes length:TestCertificateSize];
    
    CFDataRef inPKCS12Data = (CFDataRef)CFBridgingRetain(PKCS12Data);
    CFStringRef password = CFSTR("test123");
    const void *keys[] = { kSecImportExportPassphrase };
    const void *values[] = { password };
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    
    OSStatus securityError = errSecSuccess;
    securityError =  SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
    if (securityError == 0) {
        CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
        const void *tempIdentity = NULL;
        tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
        identityRef = (SecIdentityRef)tempIdentity;
        const void *tempTrust = NULL;
        tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
        trustRef = (SecTrustRef)tempTrust;
    } else {
        NSLog(@"Failed with error code %d",(int)securityError);
        return nil;
    }
    
    SecIdentityCopyCertificate(identityRef, &certificateRef);
    NSArray *result = [[NSArray alloc] initWithObjects:(id)CFBridgingRelease(identityRef), (id)CFBridgingRelease(certificateRef), nil];
    
    return result;
}



/*
 - (BOOL)expectsRequestBodyFromMethod:(NSString *)method atPath:(NSString *)path {
    return YES;
}
*/

- (void)startConnection
{
    mBodyLen = 0;
    mBody = nil;
    mResponseData = nil;
    [super startConnection];
}

- (void)prepareForBodyWithSize:(UInt64)contentLength {
    if (mBody != nil) {
        //[mBody release];
        mBody = nil;
    }
    mBodyLen = contentLength;
    mBody = [[NSMutableData alloc] initWithCapacity:contentLength];
}

- (void)processBodyData:(NSData *)postDataChunk {
    // only up to 256 Kb !!! - if larger we must accumulate data !
    if (mBody == nil) {
        mBody = [[NSMutableData alloc] initWithCapacity:(128*1024)];
    }
    [mBody appendData:postDataChunk];
}

- (void)finishBody
{
    if (mBody != nil) {
        [request setBody:mBody];
    }
}


- (void)replyToHTTPRequest {
    
    NSString *requestUri = [self requestURI];
    
    NSURL* nsurl = [NSURL URLWithString:requestUri];
    NSString *requestMethod = [request method];
    NSDictionary* requestHeaders = [request allHeaderFields];
    NSData* requestBody = [request body];
    
    
    
    
    
    const char* uri = [[nsurl path] UTF8String];
    const char* method = [requestMethod UTF8String];
    const char* body = [requestBody bytes];
    int bodylen = (int)requestBody.length;
    const char* query = [[nsurl query] UTF8String];
    
    void* cHeaders = rho_http_init_headers_list();
    
    for (NSString* key in requestHeaders) {
      NSString* value = [requestHeaders objectForKey:key];
      
      rho_http_add_header(cHeaders, [key UTF8String], [value UTF8String]);
      
    }
    
    int len = 0;
    
    //if ([requestUri isEqualToString:@"/system/js_api_entrypoint"]) {
    //    int o= 9;
    //    o = 0;
    //}
    
    
    
    const char* response = rho_http_direct_request(method, uri, query, cHeaders, body, bodylen, &len);
    
    rho_http_free_headers_list(cHeaders);
    if (mBody != nil) {
        //int c = [mBody retainCount];
        //[mBody release];
        mBody = nil;
        mBodyLen = 0;
        //[request setBody:nil];
    }

    
    //CRhoURLResponse* resp = nil;
    
    if ( response != 0 ) {
      
      /*
       // parse http responce for prepare detailed responce instead of raw data
       // not used currently - just send raw data
       
      self.httpStatusCode = 0;
      self.httpBody = nil;
      self.httpHeaderName = nil;
      self.httpHeaders = nil;
      
      http_parser_settings settings;
      settings.on_header_field = on_http_header;
      settings.on_header_value = on_http_header_value;
      settings.on_body = on_http_body;
      settings.on_status = on_http_status;
      
      settings.on_headers_complete = on_http_cb;
      settings.on_message_begin = on_http_cb;
      settings.on_message_complete = on_http_cb;
      settings.on_url = on_http_data_cb;
      http_parser *parser = malloc(sizeof(http_parser));
      parser->data = self;
      http_parser_init(parser, HTTP_RESPONSE);
      http_parser_execute(parser, &settings, response, len);
      
      NSString* strHttpVer = [NSString stringWithFormat:@"%d.%d",parser->http_major,parser->http_minor];
      
      self.httpStatusCode = parser->status_code;
      
      free(parser);
       */
        
        //NSMutableData* responseData = [NSMutableData dataWithCapacity:len];
        //[responseData appendBytes:response length:len];
        if (mResponseData != nil) {
            //[mResponseData release];
            mResponseData = nil;
        }
        mResponseData = [[NSData alloc] initWithBytes:response length:len];
        //[(NSMutableData*)mResponseData appendBytes:response length:len];
        rho_http_free_response(response);

        
        //char a[1];
        //a[0] = 0;
        //NSData* zz = [NSData dataWithBytes:a length:1];

        [asyncSocket writeData:mResponseData withTimeout:TIMEOUT_WRITE_BODY tag:HTTP_FINAL_RESPONSE];

        //[mResponseData release];

        //[self finishResponse];
    }
    else {
        [self handleResourceNotFound];
    }
    
    // totally replace responce functionality
    //[super replyToHTTPRequest];
}


- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    // Inform the http response that we're done
    if ([httpResponse respondsToSelector:@selector(connectionDidClose)])
    {
        [httpResponse connectionDidClose];
    }
    
    if (tag == HTTP_FINAL_RESPONSE)
    {
        // Cleanup after the last request
        [self finishResponse];
        
        // Terminate the connection
        [asyncSocket disconnect];
        
        mResponseData = nil;
         
        // Explictly return to ensure we don't do anything after the socket disconnects
        return;
    }
}

@end
